home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Ian & Stuart's Australian Mac 1993 September
/
clonecd
/
September 93.img
/
Archives
/
Fun, Tricks & Hacks
/
Windows
/
MSWindows.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-06-14
|
34KB
|
1,289 lines
#include "MSWindows.h"
/* Globals */
Boolean gDone = false;
RGBColor gBlack,gWhite,gGray,gLtGray,gDkGray,gBlue;
MSWindowPtr gPMWindow;
MSWindowPtr gMineWindow;
MSWindowPtr gAlertWindow;
GWorldPtr gGWorld = nil; /* Offscreen GWorld */
short gSound = true; /* use sound blaster */
short gOptions[] = { 1,0,1 }; /* Options menu items (base 0) */
MSChildPtr gChild[iMaxChild];
RgnHandle gUpRgn,gRightRgn,gURightRgn,gDRightRgn,gArrowRgn;
RgnHandle gcUpRgn,gcRightRgn,gcURightRgn,gcDRightRgn,gcArrowRgn;
RgnHandle gClipRgn,gViewRgn,gDrawRgn,gFrameRgn,gParentFrameRgn;
PicHandle gPicts[kMaxPict];
Str31 gPictText[kMaxPict];
extern unsigned long gStartTime;
extern short gGameType;
extern Boolean gMarks;
extern MenuHandle gMenus[menuCount];
/* gMac is used to hold the result of a SysEnvirons call. This makes
it convenient for any routine to check the environment. */
extern SysEnvRec gMac; /* set up by Initialize */
extern short gClicks; /* Click counter, = 1 single click */
/* = 2 double click */
/* etc. */
#pragma segment TheApp
void HideIcon(MSIconPtr icon)
{
MSChildPtr MSGroup;
MSGroup = icon->group;
SetPort((WindowPtr)MSGroup->window);
SetOrigin( -MSGroup->origin.h, -MSGroup->origin.v);
EraseRect(&icon->iconBox);
InvalRect(&icon->iconBox);
OffsetRect(&icon->iconBox,kOffscreenOffset,0);
EraseRect(&icon->textBox);
InvalRect(&icon->textBox);
OffsetRect(&icon->textBox,kOffscreenOffset,0);
SetOrigin(0,0);
}
void ShowIcon(MSIconPtr icon)
{
MSChildPtr MSGroup;
MSGroup = icon->group;
SetPort((WindowPtr)MSGroup->window);
SetOrigin( -MSGroup->origin.h, -MSGroup->origin.v);
OffsetRect(&icon->iconBox,-kOffscreenOffset,0);
InvalRect(&icon->iconBox);
OffsetRect(&icon->textBox,-kOffscreenOffset,0);
InvalRect(&icon->textBox);
SetOrigin(0,0);
}
#pragma segment Initialize
MSChildPtr NewMSChild(MSWindowPtr window,StringPtr title,
short x,short y,short h,short v,short grow,short minmax)
{
short i;
MSChildPtr MSChild;
MSChild = (MSChildPtr)NewPtrClear(sizeof(MSChildRecord));
MSChild->window = window;
MSChild->next = window->child;
window->child = MSChild;
for (i = 0; i <= title[0]; i++)
MSChild->title[i] = title[i];
MSChild->origin.h = x;
MSChild->origin.v = y;
SetRect(&MSChild->portRect, 0, 0, h * kIconStepH + 2 * kGrowBorder,
v * kIconStepV + kPictHeight + kIconHdr + 2 * kGrowBorder);
MSChild->growBorder = grow;
MSChild->minmax = minmax;
SizeMSWindow(MSChild);
return(MSChild);
}
MSWindowPtr NewMSWindow(StringPtr title,short x,short y,short h,short v,short grow)
// if x and y are 0,0, then find the max device and center on it
// otherwise, x and y are offsets from the topleft of gPMWindow
{
#pragma unused (grow)
WindowPtr window;
Point p;
window = GetNewCWindow(rWindow, NewPtrClear(sizeof(MSWindowRecord)), (WindowPtr) -1);
SizeWindow(window, h * kIconStepH + 2 * kGrowBorder,
v * kIconStepV + kPictHeight + kIconHdr + 2 * kGrowBorder,true); // fUpdate
if (x==0 && y==0) { // for gPMWindow
GDHandle dev;
dev = GetMaxDevice( &(**GetGrayRgn()).rgnBBox );
p = CenterWithin( &window->portRect, &(**dev).gdRect );
}
else
{
WindowPtr saved;
p.h = x; p.v = y;
GetPort(&saved);
SetPort((GrafPtr)gPMWindow); // will have been made by now
LocalToGlobal(&p);
SetPort(saved);
}
MoveWindow(window,p.h,p.v,true); // front
SetWTitle(window,title);
return((MSWindowPtr)window);
}
void NewMSMenu(MSChildPtr MSChild,short id)
{
MSMenuPtr menu,lastmenu;
short i,sz;
StringPtr text;
MSChild->menuBarRect.bottom = MSChild->menuBarRect.top + kMenuHeight;
menu = (MSMenuPtr)NewPtrClear(sizeof(MSMenuRecord));
lastmenu = (MSMenuPtr)(&MSChild->menu);
while (lastmenu->next != nil)
lastmenu = lastmenu->next;
lastmenu->next = menu;
menu->menu = GetMenu(id);
InsertMenu(menu->menu,-1); /* install popup menu */
text = (*(menu->menu))->menuData;
sz = text[0];
if (sz > 31) sz = 31;
menu->text[0] = sz;
for (i = 1; i <= sz; i++)
menu->text[i] = text[i];
}
void SetMSMenu(MSChildPtr MSChild)
{
Rect box;
MSMenuPtr menu;
box = MSChild->menuBarRect;
box.right = 10;
menu = MSChild->menu;
while (menu) {
box.left = box.right;
box.right += 2*10 + StringWidth((StringPtr)(menu->text));
menu->box = box;
menu = menu->next;
}
}
MSIconPtr NewMSIcon(MSChildPtr MSChild,short id,short x,short y,short action)
{
MSIconPtr icon;
icon = (MSIconPtr)NewPtrClear(sizeof(MSIconRecord));
icon->next = MSChild->iconList;
MSChild->iconList = icon;
icon->id = id;
if (x < 0)
x = -x;
else
x = x * kIconStepH + kIconXOffset;
if (y < 0)
y = -y;
else
y = y * kIconStepV + kPictHeight + kIconHdr;
SetRect(&icon->iconBox,x,y,x+32,y+32);
icon->group = MSChild;
icon->action = action;
return(icon);
}
Boolean InitializeApp(void)
{
MSChildPtr PMChild,MSChild;
MSIconPtr gameIcon;
short i,inx,id;
Handle pict;
ResType type;
Str255 text;
/*
** Test the computer to be sure we can do color.
*/
if (gMac.hasColorQD == false) {
SysBeep (50);
ExitToShell(); /* If no color QD, we must leave. */
}
gUpRgn = NewRgn(); // some cursor regions
gRightRgn = NewRgn();
gURightRgn = NewRgn();
gDRightRgn = NewRgn();
gArrowRgn = NewRgn();
gcUpRgn = NewRgn(); // more child cursor regions
gcRightRgn = NewRgn();
gcURightRgn = NewRgn();
gcDRightRgn = NewRgn();
gcArrowRgn = NewRgn();
gClipRgn = NewRgn(); // some clipping regions
gViewRgn = NewRgn();
gDrawRgn = NewRgn();
gFrameRgn = NewRgn();
gParentFrameRgn = NewRgn();
inx = 1;
while (pict = Get1IndResource('PICT',inx++)) { // Preload the PICTs
GetResInfo(pict,&id,&type,text);
if (id < kMaxPict) {
gPicts[id] = (PicHandle)pict;
for (i = text[0] + 1; i >= 0; i--)
gPictText[id][i] = text[i];
DetachResource(pict);
MoveHHi(pict);
HLock(pict); // Who need memory management ???
}
}
/* Create the windows */
gPMWindow = NewMSWindow("\pProgram Manager",0,0,6,6,kGrowBorder);
PMChild = NewMSChild(gPMWindow,"\pProgram Manager",0,0,6,6,kGrowBorder,kMinMax);
NewMSMenu(PMChild,mWinFile);
NewMSMenu(PMChild,mOptions);
NewMSMenu(PMChild,mWindow);
NewMSMenu(PMChild,mHelp);
SetMSMenu(PMChild);
PMChild->icon = NewMSIcon(PMChild,kProgramManager,0,0,0); // mini window ??
HideIcon(PMChild->icon);
MSChild = NewMSChild(gPMWindow,"\pMain",20,60,3,2,kGrowBorder,kMinMax);
gChild[iMain] = MSChild;
MSChild->icon = NewMSIcon(PMChild,kMain,0,5,0);
HideIcon(MSChild->icon);
NewMSIcon(MSChild,kFileManager,0,0,kBadPath);
NewMSIcon(MSChild,kDosPrompt,1,0,kUAEError);
MSChild->iconList->selected = true; // kDosPrompt
NewMSIcon(MSChild,kControlPanel,2,0,kDrWatson);
NewMSIcon(MSChild,kClipboard,0,1,kNot3Error);
NewMSIcon(MSChild,kPrintManager,1,1,kLostPath);
MSChild = NewMSChild(gPMWindow,"\pAccessories",360,60,2,3,kGrowBorder,kMinMax);
gChild[iAccessories] = MSChild;
MSChild->icon = NewMSIcon(PMChild,kAccessories,1,5,0);
HideIcon(MSChild->icon);
NewMSIcon(MSChild,kNotepad,0,0,kBadDir);
NewMSIcon(MSChild,kCalendar,1,0,kAssocError);
MSChild->iconList->selected = true; // kCalendar
NewMSIcon(MSChild,kPaintbrush,0,1,kNoMem);
NewMSIcon(MSChild,kCalculator,1,1,kUAEError);
NewMSIcon(MSChild,kCardfile,0,2,kNot3Error);
NewMSIcon(MSChild,kClock,1,2,kAppClockErr);
MSChild = NewMSChild(gPMWindow,"\pApplications",70,230,2,1,kGrowBorder,kMinMax);
gChild[iApplications] = MSChild;
MSChild->icon = NewMSIcon(PMChild,kApplications,3,5,0);
HideIcon(MSChild->icon);
NewMSIcon(MSChild,kTerminal,0,0,kNoComm);
MSChild->iconList->selected = true; // kTerminal
MSChild = NewMSChild(gPMWindow,"\pGames",200,190,2,2,kGrowBorder,kMinMax);
gChild[iGames] = MSChild;
MSChild->icon = NewMSIcon(PMChild,kGames,2,5,0);
HideIcon(MSChild->icon);
PMChild->iconList->selected = true; // game
NewMSIcon(MSChild,kMinesweeper,0,0,0);
gameIcon = MSChild->iconList;
MSChild->iconList->selected = true; // kMinesweeper
NewMSIcon(MSChild,kSolitare,1,0,kAssocError);
NewMSIcon(MSChild,kReversi,0,1,kNoMem);
gMineWindow = NewMSWindow("p\WinMines",160,20,0,0,0);
MSChild = NewMSChild(gMineWindow,"\pWinMines",0,0,0,0,0,kMinMax);
NewMSMenu(MSChild,mMines);
NewMSMenu(MSChild,mMineHelp);
SetMSMenu(MSChild);
MSChild->icon = NewMSIcon(PMChild,kMinesweeper,4,5,0);
HideIcon(MSChild->icon);
MSChild->icon->app = gMineWindow;
gameIcon->app = gMineWindow;
gAlertWindow = NewMSWindow("\pInvalid Path",180,120,4,2,0);
MSChild = NewMSChild(gAlertWindow,"\pInvalid Path",0,0,4,2,0,kNoMinMax);
NewMSIcon(MSChild,kCautionIcon,-(kIconHdr+kGrowBorder),-50,0);
NewMSIcon(MSChild,kErrorIcon,-(kIconHdr+kGrowBorder),-50,0);
NewMSIcon(MSChild,kInfoIcon,-(kIconHdr+kGrowBorder),-50,0);
gBlack.red = gBlack.green = gBlack.blue = vBLACK;
gWhite.red = gWhite.green = gWhite.blue = vWHITE;
gLtGray.red = gLtGray.green = gLtGray.blue = vLTGRAY;
gGray.red = gGray.green = gGray.blue = vGRAY;
gDkGray.red = gDkGray.green = gDkGray.blue = vDKGRAY;
gBlue.red = vDKGRAY; gBlue.green = vGRAY; gBlue.blue = vWHITE;
GetDateTime(&gStartTime);
qd.randSeed = gStartTime;
gGameType = iIntermediate - iBeginner;
NewGame(false);
ShowWindow((WindowPtr)gPMWindow);
return(true);
}
#pragma segment TheApp
void SizeMSWindow(MSChildPtr MSChild)
{
Rect box;
box = MSChild->portRect;
box.bottom = kPictHeight;
box.left = box.right - kPictWidth;
MSChild->maximizeBox = box;
box.right = box.left;
box.left = box.right - kPictWidth2;
MSChild->minimizeBox = box;
box.right = kPictWidth;
box.left = 0;
MSChild->controlMenuBox = box;
box.right = 0;
MSChild->controlMenuRect = box;
box = MSChild->portRect;
box.top = kPictHeight;
box.bottom = box.top + ((MSChild->menu != nil) ? kMenuHeight : 0); // a menu ??
InsetRect(&box,MSChild->growBorder,0);
MSChild->menuBarRect = box;
SetCursorRgns();
}
void
DrawIconText(MSIconPtr icon,short active)
{
EraseRect(&icon->textBox);
if (active && icon->selected) {
RGBForeColor(&gBlue); // the text hilite color
PaintRect(&icon->textBox);
RGBForeColor(&gBlack);
}
MoveTo(icon->textBox.left + 6,icon->textBox.bottom - 4);
DrawString(gPictText[icon->id]);
}
void
DrawPictBox(short id,Rect *box)
{
PicHandle pict;
if (pict = gPicts[id])
DrawPicture(pict,box);
}
void
DrawIcon(MSIconPtr icon,short active)
{
PicHandle pict;
short w;
Rect box;
if (pict = gPicts[icon->id]) {
box = icon->iconBox;
DrawPicture(pict,&box);
if (w = StringWidth(gPictText[icon->id])) {
box.left += (kIconSize - w) / 2;
box.right = box.left + w;
box.bottom = icon->iconBox.bottom + kIconLineHeight;
InsetRect(&box,-6,-4);
box.top = icon->iconBox.bottom;
icon->textBox = box;
DrawIconText(icon,active);
}
}
}
Boolean TrackTextBox(Rect *box)
{
Point where;
reclick:
while (StillDown()) {
GetMouse(&where);
if (PtInRect(where,box)) {
InvertRect(box);
while (StillDown()) {
GetMouse(&where);
if (!PtInRect(where,box)) { // dragged out of the box
InvertRect(box);
goto reclick; // try again
}
}
InvertRect(box);
return(true);
}
}
return(false);
}
Boolean TrackButton(short id,Rect *box)
{
Point where;
reclick:
while (StillDown()) {
GetMouse(&where);
if (PtInRect(where,box)) {
DrawCell(id+kPressOffset,box);
while (StillDown()) {
GetMouse(&where);
if (!PtInRect(where,box)) { // dragged out of the box
DrawCell(id,box);
goto reclick; // try again
}
}
DrawCell(id,box);
return(true);
}
}
return(false);
}
void ClickIcon(MSChildPtr MSChild,Point where,long modifiers)
{
#pragma unused (modifiers)
MSIconPtr icon,lasticon;
icon = MSChild->iconList;
while (icon) {
if (PtInRect(where,&icon->iconBox) ||
PtInRect(where,&icon->textBox)) {
lasticon = MSChild->iconList;
while (lasticon) {
if (lasticon->selected) { // bug, we don't drag multi clicks
if (icon == lasticon) {
if (gClicks == 2)
DoubleClickIcon(MSChild,icon);
return;
}
DrawIconText(lasticon,lasticon->selected = false);
goto select; // clear selection drawn below
}
lasticon = lasticon->next;
}
break; // a hit
}
icon = icon->next;
}
return; // no hit
reclick:
while (StillDown()) {
GetMouse(&where);
if (PtInRect(where,&icon->iconBox) ||
PtInRect(where,&icon->textBox)) {
select:
DrawIconText(icon,icon->selected = true);
while (StillDown()) {
GetMouse(&where);
if (!(PtInRect(where,&icon->iconBox) ||
PtInRect(where,&icon->textBox))) { // dragged out of the box
DrawIconText(icon,icon->selected = false);
goto reclick; // turn off and try again
}
}
return; // good hit
}
}
DrawIconText(lasticon,lasticon->selected = true); // restore last one
}
void DoMSCommand(MSChildPtr MSChild,short command)
{
Rect view;
WindowPtr window;
MSChildPtr MSNextChild,MSParent;
window = (WindowPtr)MSChild->window;
SetPort(window); /* the window must be the current port... */
SetOrigin(0,0);
switch (command) {
case vMinimize:
if (MSChild->next == nil) {
HideWindow(window);
window = FrontWindow();
SetPort(window);
} else {
view = MSChild->portRect;
OffsetRect(&view,MSChild->origin.h,MSChild->origin.v);
EraseRect(&view);
InvalRect(&view);
MSChild->icon->restore = MSChild;
MSChild->origin.h |= kOffscreenOffset;
if (MSChild->active) {
MSNextChild = MSChild->next;
while (MSNextChild && (MSNextChild->origin.h & kOffscreenOffset))
MSNextChild = MSNextChild->next;
if (MSNextChild) {
MSNextChild->active = true;
view = MSNextChild->portRect;
OffsetRect(&view,MSNextChild->origin.h,MSNextChild->origin.v);
EraseRect(&view);
InvalRect(&view);
}
}
}
ShowIcon(MSChild->icon);
SetCursorRgns();
break;
case vRestore:
if (!MSChild->maximized) {
if (gSound) SysBeep(4);
} else
if (MSChild->iconList) { // PM windows only !!
EraseRect(&MSChild->portRect);
InvalRect(&MSChild->portRect);
MSChild->portRect = MSChild->restoreRect;
MSChild->origin = MSChild->restoreOrigin;
if (MSChild->next == nil) // base child
SizeWindow(window,MSChild->portRect.right,MSChild->portRect.bottom,true);
SizeMSWindow(MSChild);
MSChild->maximized = false;
}
break;
case vMaximize:
if (MSChild->maximized) {
if (gSound) SysBeep(4);
} else
if (MSChild->iconList) { // PM windows only !!
MSChild->restoreRect = MSChild->portRect;
MSChild->restoreOrigin = MSChild->origin;
MSParent = MSChild->next;
if (MSParent == nil) { // base child
MoveWindow(window,0,20,true); // menusize
SizeWindow(window,qd.screenBits.bounds.right,
qd.screenBits.bounds.bottom - 20,true);
MSChild->portRect = window->portRect;
} else {
while (MSParent->next != nil)
MSParent = MSParent->next;
MSChild->portRect = MSParent->portRect;
MSChild->portRect.bottom -= MSParent->menuBarRect.bottom;
MSChild->origin.h = 0;
MSChild->origin.v = MSParent->menuBarRect.bottom;
}
EraseRect(&MSChild->portRect);
InvalRect(&MSChild->portRect);
SizeMSWindow(MSChild);
MSChild->maximized = true;
}
break;
}
}
void DoControlMenu(MSChildPtr MSChild,Point where)
{
#pragma unused (where)
Point pt;
MenuHandle menu;
pt.h = MSChild->controlMenuBox.left;
pt.v = MSChild->controlMenuBox.bottom;
LocalToGlobal(&pt);
menu = gMenus[mControlInx];
if ( MSChild->window == gAlertWindow ) {
DisableItem(menu, iMinimize); /* the alert doesn't minimize */
DisableItem(menu, iMaximize);
} else {
EnableItem(menu, iMinimize);
EnableItem(menu, iMaximize);
}
DoMenuCommand(MSChild,menu,PopUpMenuSelect(menu,pt.v,pt.h,1) );
}
void DoMenuBar(MSChildPtr MSChild,Point where)
{
Point pt;
MSMenuPtr menu;
pt = where;
while(StillDown()) {
menu = MSChild->menu;
while (menu) {
if (PtInRect(pt,&menu->box)) // ??
break;
menu = menu->next;
}
if (menu) {
InvertRect(&menu->box);
pt.h = menu->box.left;
pt.v = menu->box.bottom;
LocalToGlobal(&pt);
DoMenuCommand(MSChild,menu->menu,PopUpMenuSelect(menu->menu,pt.v,pt.h,1) );
InvertRect(&menu->box);
}
GetMouse(&where);
}
}
void SetOkBox(WindowPtr window,Rect *box)
{
*box = window->portRect;
box->left = (box->right - kOKBoxW) / 2;
box->right = box->left + kOKBoxW;
box->bottom -= 10;
box->top = box->bottom - kOKBoxH;
}
void DrawOkBox(WindowPtr window)
{
Rect box;
PicHandle pict;
SetOkBox(window,&box);
if (pict = gPicts[kOKButton])
DrawPicture(pict,&box);
}
void DrawAlertWindow(WindowPtr window)
{
short i,c,x,y,count;
MSChildPtr MSChild;
Str255 text;
StringPtr ptext,p;
DrawMSWindow(window);
MSChild = ((MSWindowPtr)window)->child;
GetIndString(text,rTextStr,MSChild->iconList->action);
DrawOkBox(window);
TextFace(bold);
x = 60; y = kIconStepV;
ptext = text;
count = (*ptext) & 0xFF;
text[count + 1] = 0;
for (i = 0; i < count; i += c + 1) {
p = ptext + 1;
c = 0;
while (((*p) & 0xFF) >= ' ') {
p++;
c++;
}
*ptext = c;
MoveTo(x,y);
DrawString(ptext);
y += 16;
ptext = p;
}
TextFace(normal);
}
void DoMSAlert(short action)
{
short i;
WindowPtr window;
MSChildPtr MSChild;
Str255 text;
MSChild = gAlertWindow->child;
MSChild->iconList->action = action;
text[0] = 0;
GetIndString(text,rTitleStr,action);
for (i = text[0] + 1; i >= 0; i--)
MSChild->title[i] = text[i];
window = (WindowPtr)gAlertWindow;
ShowWindow(window);
SelectWindow(window);
InvalRect(&window->portRect);
if (gSound) SysBeep(4);
}
void DoubleClickIcon(MSChildPtr MSChild,MSIconPtr icon)
{
Point where;
WindowPtr window;
if (icon->app) {
if (MSChild->next == nil) // the PM base group
HideIcon(icon);
window = (WindowPtr)icon->app;
ShowWindow(window); // was hidden, restore
SelectWindow(window);
SetPort(window);
} else
if (icon->restore) {
if (icon->iconBox.right < kOffscreenOffset) // for Window menu
HideIcon(icon);
MSChild = icon->restore;
window = (WindowPtr)MSChild->window;
SetPort(window);
SetOrigin(0,0); // redundant ??
MSChild->origin.h &= ~kOffscreenOffset;
where = MSChild->origin;
LocalToGlobal(&where);
BringChildFront(window,where,true);
} else
if (icon->action)
DoMSAlert(icon->action);
}
/* This is called when a mouse-down event occurs in the content of a window.
Other applications might want to call FindControl, TEClick, etc., to
further process the click. */
Boolean ContentClick(EventRecord *event,WindowPtr window)
{
Point pt;
Rect box;
MSChildPtr MSChild;
CountClicks(event); // count for double clicks
MSChild = ((MSWindowPtr)window)->child;
while (MSChild != nil) {
SetOrigin( -MSChild->origin.h, -MSChild->origin.v);
pt = event->where;
GlobalToLocal(&pt);
if (PtInRect(pt,&MSChild->portRect)) {
if ((MSChild->next != nil) && (MSChild->window->child != MSChild)) {
BringChildFront(window,event->where,true);
MSChild = ((MSWindowPtr)window)->child;
SetOrigin( -MSChild->origin.h, -MSChild->origin.v);
pt = event->where;
GlobalToLocal(&pt);
}
if (PtInRect(pt,&MSChild->controlMenuRect)) // is the menu already up ?
DoControlMenu(MSChild,pt);
else
if (PtInRect(pt,&MSChild->menuBarRect)) // is there a window menu bar ?
DoMenuBar(MSChild,pt);
else
if (pt.v < kPictHeight) {
if (PtInRect(pt,&MSChild->controlMenuBox)) {
DrawCell(kMenuBox+kPressOffset,&MSChild->controlMenuBox);
DoControlMenu(MSChild,pt);
DrawCell(kMenuBox,&MSChild->controlMenuBox);
} else
if (PtInRect(pt,&MSChild->maximizeBox)) {
if (TrackButton((MSChild->maximized) ? kRestoreBox : kMaximizeBox,&MSChild->maximizeBox))
DoMSCommand(MSChild,(MSChild->maximized) ? vRestore : vMaximize);
} else
if (PtInRect(pt,&MSChild->minimizeBox)) {
if (TrackButton(kMinimizeBox,&MSChild->minimizeBox))
DoMSCommand(MSChild,vMinimize);
} else {
// SetOrigin( 0, 0);
return(false); // allow dragging
}
} else
if (window == gMineWindow) {
if (PtInGame(pt)) {
SetPort(window);
ClickGame(pt,event->modifiers);
}
} else
if (window == gAlertWindow) {
SetOkBox(window,&box);
if (PtInRect(pt,&box)) {
if (TrackButton(kOKButton,&box)) {
if (gDone)
Terminate(); // this is the end...
else
HideWindow(window);
}
}
} else
ClickIcon(MSChild,pt,event->modifiers);
MSChild = nil;
} else
MSChild = MSChild->next;
}
SetOrigin( 0, 0);
return(true);
} /*ContentClick*/
void DrawMSWindow(WindowPtr window)
{
short x,x1,y,vBorder;
Rect r,box;
MSIconPtr icon;
MSChildPtr MSParent,MSChild;
MSMenuPtr menu;
MSParent = ((MSWindowPtr)window)->child;
while (MSParent->next != nil)
MSParent = MSParent->next;
MSChild = ((MSWindowPtr)window)->child;
/* start with parent's client area */
r = MSParent->portRect;
RectRgn(gParentFrameRgn,&r);
InsetRect(&r,kGrowBorder,kGrowBorder);
r.top = MSParent->menuBarRect.bottom;
RectRgn(gClipRgn,&r);
DiffRgn(gParentFrameRgn,gClipRgn,gParentFrameRgn); // find parent frame region
while (MSChild != nil) {
if (!(MSChild->origin.h & kOffscreenOffset)) { // on screen
SetOrigin( -MSChild->origin.h, -MSChild->origin.v);
OffsetRgn(gClipRgn, -MSChild->origin.h, -MSChild->origin.v);
RectRgn(gViewRgn,&MSChild->portRect);
SectRgn(gClipRgn,gViewRgn,gDrawRgn); // find my clip
if (MSChild == MSParent) {
SetClip(gParentFrameRgn);
UnionRgn(gDrawRgn,gParentFrameRgn,gDrawRgn);
} else {
r = MSChild->portRect;
InsetRect(&r,kGrowBorder,kGrowBorder);
r.top = MSChild->menuBarRect.bottom;
RectRgn(gFrameRgn,&r);
DiffRgn(gDrawRgn,gFrameRgn,gFrameRgn); // find my client area
DiffRgn(gClipRgn,gViewRgn,gClipRgn); // subtract the drawn view
OffsetRgn(gClipRgn, MSChild->origin.h, MSChild->origin.v);
SetClip(gFrameRgn);
}
icon = MSChild->iconList;
if (icon) { // assume PM windows have at lease one icon, game has none
box = MSChild->portRect;
FrameRect(&box);
InsetRect(&box,1,1);
if (MSChild->active)
RGBForeColor(&gGray);
else
RGBForeColor(&gWhite);
PenSize(2,2);
FrameRect(&box);
RGBForeColor(&gBlack);
PenNormal();
InsetRect(&box,2,2);
FrameRect(&box);
}
x = 0;
y = 0;
vBorder = (MSChild->active) ? 0 : kInactiveOffset;
DrawPict(kMenuBox + vBorder,&x,&y);
for ( ; x < MSChild->portRect.right; )
DrawPict(kTop + vBorder,&x,&y);
x = MSChild->portRect.right - kPictWidth;
if (MSChild->minmax) {
x -= kPictWidth2;
DrawPict(kMinimizeBox + vBorder,&x,&y);
DrawPict(((MSChild->maximized) ? kRestoreBox : kMaximizeBox) + vBorder,&x,&y);
} else {
MSChild->minimizeBox.right = MSChild->minimizeBox.left;
MSChild->maximizeBox.right = MSChild->maximizeBox.left;
DrawPict(kNoBox + vBorder,&x,&y);
}
SetClip(gDrawRgn);
x -= StringWidth(MSChild->title) + 2*kPictWidth2;
MoveTo(x / 2,kPictHeight - 6); // -5 with 14pt
TextFont(applFont);
TextFace(bold);
if (MSChild->active) {
RGBForeColor(&gWhite);
DrawString(MSChild->title);
RGBForeColor(&gBlack);
} else
DrawString(MSChild->title);
TextFace(normal);
if (icon) { // assume PM windows have at lease one icon, game has none
x1 = MSChild->portRect.right - kPictWidth;
x = 0;
y = MSChild->portRect.bottom - kPictHeight;
DrawPict(kBottomLeft + vBorder,&x,&y);
x = x1;
DrawPict(kBottomRight + vBorder,&x,&y);
while (icon) {
DrawIcon(icon,MSChild->active && (MSChild->window->child == MSChild));
icon = icon->next;
}
}
if (MSChild->menuBarRect.bottom != MSChild->menuBarRect.top) {
EraseRect(&MSChild->menuBarRect);
TextFace(bold);
menu = MSChild->menu;
while (menu) {
MoveTo(menu->box.left + 10,menu->box.bottom - 4);
DrawString((StringPtr)menu->text);
menu = menu->next;
}
TextFace(normal);
MoveTo(MSChild->menuBarRect.left,MSChild->menuBarRect.bottom);
LineTo(MSChild->menuBarRect.right,MSChild->menuBarRect.bottom);
}
}
MSChild = MSChild->next;
}
SetOrigin(0,0);
/* restore a big rectangular region */
SetRectRgn(gClipRgn, -8000, -8000, 8000, 8000);
SetClip(gClipRgn);
}
Boolean DragChild(WindowPtr window,Point where)
{
Point pt;
long xy;
Rect childRect,limitRect,slopRect;
MSChildPtr MSParent,MSChild;
RgnHandle rgn;
SetPort(window);
SetOrigin(0,0); // redundant ??
pt = where;
GlobalToLocal(&pt);
MSChild = ((MSWindowPtr)window)->child;
while (MSChild->next != nil) {
childRect = MSChild->portRect;
OffsetRect(&childRect,MSChild->origin.h,MSChild->origin.v);
if (PtInRect(pt,&childRect)) {
rgn = NewRgn();
RectRgn(rgn,&childRect);
MSParent = MSChild->next;
while (MSParent->next != nil)
MSParent = MSParent->next;
limitRect = MSParent->portRect;
InsetRect(&limitRect,kGrowBorder + 1,kGrowBorder + 1); // + 1 is slop ??
limitRect.top = MSParent->menuBarRect.bottom + 1; // + 1 is slop ??
slopRect = limitRect;
InsetRect(&slopRect,-50,-50);
xy = DragGrayRgn(rgn,pt,&limitRect,&slopRect,0,nil);
// hysteresis ??
if (xy != 0x80008000) {
EraseRect(&childRect);
InvalRect(&childRect);
OffsetRect(&childRect, LoWrd(xy), HiWrd(xy));
EraseRect(&childRect);
InvalRect(&childRect);
*(long*)&MSChild->origin += xy;
}
DisposeRgn(rgn);
return(true);
}
MSChild = MSChild->next;
}
return(false);
}
/* Draw the contents of the application window. We do some drawing in color, using
Classic QuickDraw's color capabilities. This will be black and white on old
machines, but color on color machines. At this point, the window’s visRgn
is set to allow drawing only where it needs to be done. */
void DrawWindow(WindowPtr window)
{
if (window == gMineWindow)
DrawMineWindow(window);
else
if (window == gAlertWindow)
DrawAlertWindow(window);
else
DrawMSWindow(window);
} /*DrawWindow*/
/*
** Read menu descriptions from resource file into memory
** and store handles in gMenus array.
** Insert into MenuBar and draw.
*/
void
SetUpMenus(void)
{
gMenus[mAppleInx] = GetMenu(mApple); /* read menus from resource file */
AddResMenu(gMenus[mAppleInx], 'DRVR'); /* add desk accessory names to Apple menu */
gMenus[mFileInx] = GetMenu(mFile);
gMenus[mEditInx] = GetMenu(mEdit);
gMenus[mControlInx] = GetMenu(mControl);
InsertMenu(gMenus[mAppleInx], 0); /* install menus in menu bar */
InsertMenu(gMenus[mFileInx], 0);
InsertMenu(gMenus[mEditInx], 0);
InsertMenu(gMenus[mControlInx], -1); /* install popup menu */
DrawMenuBar(); /* and draw menu bar */
}
/*
** Display a dialog box
*/
void
ShowDialog(short dialogID)
{
DialogPtr theDialog;
short itemHit;
SetCursor(*GetCursor(kArrowCursor));
theDialog = GetNewDialog(dialogID, nil, (WindowPtr) -1);
PositionWindow( (WindowPtr) theDialog); // •••ets
ModalDialog(nil,&itemHit);
DisposDialog(theDialog);
}
/* This is called when an item is chosen from the menu bar (after calling
MenuSelect or MenuKey). It performs the right operation for each command.
It is good to have both the result of MenuSelect and MenuKey go to
one routine like this to keep everything organized. */
void
DoMenuCommand(MSChildPtr MSChild,MenuHandle hMenu,long mResult)
{
short theItem, /* menu item number from mResult low-order word */
theMenu; /* menu number from mResult high-order word */
Str255 name; /* desk accessory name */
int temp;
Boolean dummy;
theItem = LoWrd(mResult); /* call Toolbox Utility routines to */
theMenu = HiWrd(mResult); /* set menu item number and menu */
switch (theMenu) { /* switch on menu ID */
case mApple:
switch (theItem) {
case iAbout: /* bring up About Box */
ShowDialog(rAbout);
break;
default: /* all non-About items in this menu are DAs */
GetItem(hMenu, theItem, name);
temp = OpenDeskAcc(name);
SetPort((WindowPtr)gMineWindow);
}
break;
case mFile:
switch (theItem) { /* switch on menu item */
case iProgramMgr:
ShowWindow((WindowPtr)gPMWindow);
break;
case iSound:
CheckItem(hMenu,theItem,gSound = !gSound);
break;
case iQuit:
goto logout;
}
break;
case mEdit:
dummy = SystemEdit(theItem - 1); /* Pass the command on to the Desk Manager. */
break;
case mWinFile:
switch (theItem) { /* switch on menu item */
case iLogout:
logout:
DoMSAlert(kExitMsg);
gDone = true;
// Terminate(); // when the OK button is pressed
break;
}
break;
case mOptions:
CheckItem(hMenu,theItem,gOptions[theItem] = !gOptions[theItem - 1]);
break;
case mWindow:
switch (theItem) {
case iCascade:
break;
case iTile:
break;
case iArrange:
break;
case iMain:
case iAccessories:
case iApplications:
case iGames:
MSChild = gChild[theItem];
MSChild->icon->restore = MSChild;
DoubleClickIcon(MSChild,MSChild->icon);
break;
}
break;
case mControl:
switch (theItem) {
case iRestore:
DoMSCommand(MSChild,vRestore);
break;
case iMove:
break;
case iWinSize:
break;
case iMinimize:
DoMSCommand(MSChild,vMinimize);
break;
case iMaximize:
DoMSCommand(MSChild,(MSChild->maximized) ? vRestore : vMaximize);
break;
case iWinClose:
HideWindow((WindowPtr)(MSChild->window));
break;
case iSwitchTo:
break;
}
break;
case mHelp:
if (theItem == iAboutHelp) /* bring up About Box */
ShowDialog(rAbout);
else
DoMSAlert(kHelpMsg);
break;
case mMineHelp:
if (theItem == iAboutMines) /* bring up About Box */
ShowDialog(rAboutMines);
else
DoMSAlert(kHelpMsg);
break;
case mMines:
switch (theItem) { /* switch on menu item */
case iBeginner:
case iIntermediate:
case iExpert:
CheckItem(hMenu, gGameType + iBeginner, false);
gGameType = theItem - iBeginner;
CheckItem(hMenu, theItem, true);
NewGame(true);
break;
case iNew:
NewGame(false);
break;
case iCustom:
ShowDialog(rCustom);
break;
case iMarks:
CheckItem(hMenu, iMarks, gMarks = !gMarks);
break;
case iTimes:
ShowDialog(rBestTimes);
break;
}
break;
}
HiliteMenu(0); /* Unhighlight menu title */
/* (highlighted by MenuSelect) */
}
void
CreateGWorld(Rect *bounds)
{
/*************************************************************************/
/* Allocate a new GWorld for the offscreen drawing and store its PixMap. */
/*************************************************************************/
if (gGWorld!= nil)
DisposeGWorld( gGWorld );
NewGWorld( &gGWorld, 8, bounds, nil, nil, 0 );
}
void
SaveBits(WindowPtr window)
{
CGrafPtr currentPort;
GDHandle currentDevice;
PixMapHandle pixMap; /* PixMap of the GWorld */
/******************************************************************************/
/* Store the current port and device before switching to the offscreen world. */
/******************************************************************************/
GetGWorld( ¤tPort, ¤tDevice );
/****************************************************************************/
/* Switch to the offscreen GWorld then lock the offscreen buffer in memory. */
/****************************************************************************/
SetGWorld( gGWorld, nil );
pixMap = gGWorld->portPixMap; // GetGWorldPixMap(gGWorld);
LockPixels( pixMap );
RGBForeColor(&gBlack);
RGBBackColor(&gWhite);
ClipRect(&window->portRect);
CopyBits(&window->portBits, (BitMap *) *pixMap,
&window->portRect, &window->portRect, srcCopy, nil);
/********************************************************************/
/* After drawing the image, unlock the offscreen buffer in memory */
/* and set the port and device back to the window's. */
/********************************************************************/
UnlockPixels( pixMap );
SetGWorld( currentPort, currentDevice );
}
void
DrawMineWindow(WindowPtr window)
{
CGrafPtr currentPort;
GDHandle currentDevice;
PixMapHandle pixMap; /* PixMap of the GWorld */
/******************************************************************************/
/* Store the current port and device before switching to the offscreen world. */
/******************************************************************************/
GetGWorld( ¤tPort, ¤tDevice );
pixMap = gGWorld->portPixMap; // GetGWorldPixMap(gGWorld);
/****************************************************************************/
/* Switch to the offscreen GWorld then lock the offscreen buffer in memory. */
/****************************************************************************/
SetGWorld( gGWorld, nil );
LockPixels( pixMap );
DrawMSWindow(window);
DrawGame( (BitMap *)*pixMap );
/********************************************************************/
/* After drawing the image, unlock the offscreen buffer in memory */
/* and set the port and device back to the window's. */
/********************************************************************/
SetGWorld( currentPort, currentDevice );
RGBForeColor(&gBlack);
RGBBackColor(&gWhite);
ClipRect(&window->portRect);
CopyBits ((BitMap *) *pixMap, &window->portBits,
&window->portRect, &window->portRect, srcCopy, nil);
UnlockPixels( pixMap );
}
#define topLeft(x) (*((Point *) &(x)))
#define botRight(x) (*((Point *) &(x)+1))
void PositionWindow( WindowPtr w )
{
WindowPtr saved;
Rect r;
Point p;
r = ((GrafPtr)gPMWindow)->portRect;
GetPort(&saved);
SetPort((GrafPtr)gPMWindow);
LocalToGlobal(&topLeft(r));
LocalToGlobal(&botRight(r));
SetPort(saved);
p = CenterWithin( &w->portRect, &r );
MoveWindow( w, p.h, p.v, false);
}
Point CenterWithin( Rect *r, Rect *within )
// within is in global coordinates
// returns global coordinate of r's topleft point
{
Point p;
p.h = within->left + ((within->right-within->left) - (r->right-r->left))/2;
p.v = within->top + ((within->bottom-within->top) - (r->bottom-r->top))/2;
return p;
}